package com.yvan.upload;

import com.yvan.upload.aliyunoss.OSSUploadUtil;
import com.yvan.upload.fastdfs.FastDFSClient;
import com.yvan.upload.fastdfs.FastDFSFile;
import com.yvan.upload.seaweedfs.SeaweedFSUtil;
import lombok.Cleanup;
import org.apache.commons.lang.StringUtils;
import org.csource.common.MyException;
import org.lokra.seaweedfs.core.file.FileHandleStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.Properties;

/**
 * 文件操作工具类对象
 *
 * @author yvan
 * @date 2020-07-01
 */
public class FileOperationUtils {

    private static Logger logger = LoggerFactory.getLogger(FileOperationUtils.class);

    private static String type = "";
    public static String activeDir = "";

    /**
     * 加载环境变量
     */
    private static void envLoading() {
        if (StringUtils.isNotBlank(type)) {
            return;
        }
        try {
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            Properties properties = new Properties();
            @Cleanup
            InputStream in = loader.getResourceAsStream("application.properties");
            properties.load(in);
            type = properties.getProperty("file.uploader");
            if (StringUtils.isBlank(activeDir)) {
                activeDir = properties.getProperty("file.settings.activeDir");
            }
        } catch (IOException e) {
            logger.error("file.uploader value", e);
        }
    }

    /**
     * 文件删除
     *
     * @param url 完整的URL访问地址
     * @return 是否删除
     */
    public static boolean delete(String url) {
        envLoading();
        try {
            if ("fastdfs".equals(type)) {
                return fastDFSDeleteFile(url);
            } else if ("seaweedfs".equals(type)) {
                return seaweedFSDeleteFile(url);
            } else if ("oss".equals(type)) {
                return ossDeleteFile(url);
            } else {
                logger.error("未选择文件服务器");
                return false;
            }
        } catch (Exception e) {
            logger.error("delete file failed", e);
            return false;
        }
    }

    /**
     * 文件上传
     *
     * @param fileName    文件名
     * @param inputStream 文件流
     * @return
     */
    public static FileUploadResultVo upload(String fileName, InputStream inputStream) throws Exception {
        envLoading();
        if ("fastdfs".equals(type)) {
            return fastDFSSaveFile(fileName, inputStream);
        } else if ("seaweedfs".equals(type)) {
            return seaweedFSSaveFile(fileName, inputStream);
        } else if ("oss".equals(type)) {
            return ossSaveFile(fileName, inputStream);
        } else {
            logger.error("未选择文件服务器");
            throw new Exception("未选择文件服务器");
        }
    }

    /**
     * @param fileName    文件名
     * @param inputStream 文件流
     * @return
     * @throws IOException 这个方法后面可以自己封装一个util,这里只是测试
     */
    private static FileUploadResultVo fastDFSSaveFile(String fileName, InputStream inputStream) throws IOException {
        String[] fileAbsolutePath = {};
        String ext = fileName.substring(fileName.lastIndexOf(".") + 1);

        int len1 = inputStream.available();
        byte[] fileBuff = new byte[len1];
        inputStream.read(fileBuff);
        FastDFSFile file = new FastDFSFile(fileName, fileBuff, ext);
        try {
            FastDFSClient.env(activeDir);
            fileAbsolutePath = FastDFSClient.upload(file);
        } catch (Exception e) {
            logger.error("upload file Exception!", e);
        }
        String fileUrl = FastDFSClient.getTrackerUrl() + fileAbsolutePath[0] + "/" + fileAbsolutePath[1];
        logger.info("上传成功: {}", fileUrl);


        FileUploadResultVo resultVo = new FileUploadResultVo();
        resultVo.setFileUrl(fileUrl);
        resultVo.setFileName(fileAbsolutePath[1]);
        resultVo.setFileExt(ext);
        resultVo.setGroupName(fileAbsolutePath[0]);
        resultVo.setFileSize((long) len1);
        inputStream.close();
        return resultVo;
    }

    /**
     * @param fileName    文件名
     * @param inputStream 文件流
     * @return
     * @throws IOException 这个方法后面可以自己封装一个util,这里只是测试
     */
    private static FileUploadResultVo seaweedFSSaveFile(String fileName, InputStream inputStream) throws IOException {
        String ext = fileName.substring(fileName.lastIndexOf(".") + 1);

        SeaweedFSUtil.env(activeDir);
        FileHandleStatus fileHandleStatus = SeaweedFSUtil.upload(inputStream, fileName);
        String fileUrl = "http://" + SeaweedFSUtil.readHost + ":" + SeaweedFSUtil.readPort + "/" + fileHandleStatus.getFileId();
        logger.info("上传成功: {}", fileUrl);

        FileUploadResultVo resultVo = new FileUploadResultVo();
        resultVo.setFileUrl(fileUrl);
        resultVo.setFileName(fileName);
        resultVo.setFileExt(ext);
        resultVo.setFileSize(fileHandleStatus.getSize());
        resultVo.setFileId(fileHandleStatus.getFileId());
        inputStream.close();
        return resultVo;

    }

    /**
     * @param fileName    文件名
     * @param inputStream 文件流
     * @return
     * @throws IOException
     */
    private static FileUploadResultVo ossSaveFile(String fileName, InputStream inputStream) throws IOException {

        String ext = fileName.substring(fileName.lastIndexOf(".") + 1);

        File targetFile = new File(System.getProperties().getProperty("java.io.tmpdir") + System.currentTimeMillis() + ".tmp");
        // FileUtils.copyInputStreamToFile(inputStream, targetFile);
        getFile(inputStream, targetFile);
        OSSUploadUtil.env(activeDir);
        String fileUrl = OSSUploadUtil.uploadFile(targetFile, ext);
        logger.info("上传成功: {}", fileUrl);

        FileUploadResultVo resultVo = new FileUploadResultVo();
        resultVo.setFileUrl(fileUrl);
        resultVo.setFileName(fileName);
        resultVo.setFileExt(ext);
        resultVo.setFileSize(targetFile.length());
        targetFile.delete();
        inputStream.close();
        return resultVo;
    }


    /**
     * @param url 文件上传
     * @return
     * @throws IOException 这个方法后面可以自己封装一个util,这里只是测试
     */
    private static boolean fastDFSDeleteFile(String url) {
        int i = url.indexOf("/group");
        url = url.substring(i + 1);
        int i1 = url.indexOf("/");
        String groupName = url.substring(0, i1);
        String fileName = url.substring(i1 + 1);
        try {
            FastDFSClient.env(activeDir);
            FastDFSClient.deleteFile(groupName, fileName);
            return true;
        } catch (IOException | MyException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @param url 文件上传
     * @return
     * @throws IOException 这个方法后面可以自己封装一个util,这里只是测试
     */
    private static boolean seaweedFSDeleteFile(String url) {
        int index = url.lastIndexOf("/");
        String fileId = url.substring(index + 1);
        try {
            SeaweedFSUtil.env(activeDir);
            SeaweedFSUtil.delete(fileId);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * @param url 文件上传
     * @return
     * @throws IOException 这个方法后面可以自己封装一个util,这里只是测试
     */
    private static boolean ossDeleteFile(String url) {
        OSSUploadUtil.env(activeDir);
        return OSSUploadUtil.deleteFile(url);
    }

    private static void getFile(InputStream is, File targetFile) throws IOException {
        byte[] buffer = new byte[is.available()];
        is.read(buffer);

        OutputStream outStream = new FileOutputStream(targetFile);
        outStream.write(buffer);
    }


    public static void main(String[] args) throws Exception {
        FileUploadResultVo upload = FileOperationUtils.upload("ED49F729-0E32-4461-A2CC-946325387E9E.png", new FileInputStream(new File("/Users/yvan/Desktop/ED49F729-0E32-4461-A2CC-946325387E9E.png")));
        System.out.println(upload.getFileUrl());
        //System.out.println(FileOperationUtils.delete("http://59.196.230.236:9333/4,01792f3421"));

    }
}
